#pragma  once
/*
THIS IS THE SECTION IN CHARGE OF CREATING RAGDOLLS

NOTE:  This is not part of the Scythe API, as any given ragdoll code is going to be renderer-specific.
I have implemented here a ragdoll class for Ogre (because Scythe uses it) that you are free to use
yourself, or as a reference for creating your own implementation if you do not use Ogre.

NOTE:  There are 2 types of skeletal animation systems in graphics engines/renderers.  The first is where each bones transformation is a simple
global value, and does not influence other bones, even children.  A ragdoll implementation is dead easy in this case.
The other type is what Ogre has and what I have implemented here.  Every bones transformation is in local space relative to its parent bone, so if you move
one you move all its children.  It is bloody hard if you have no methods to directly set a bones global orientation, because then you have to convert the physics
objects global transformation into each bones local space, taking into account its parents transformation...  But its all done for you here so if you 
don't have an advance maths education you will find this code a godsend.
*/

#include "head.h"
#include "Scythe.h"

extern Scythe::PhysicsClass physics;

class ScytheSkeleton;
class ScytheBone
{
public:
	ScytheBone() { bone = 0; }
	string				name;
	Ogre::Bone*			bone;

	bool					isActor;		//true if connected to a physics actor
	bool					isRoot;		//true if this is the root of the skeleton

	vector<ScytheBone*>		childBones;
	void					render(Scythe::SkeletonData* skeletalID,  Ogre::Vector3 modelpos, Ogre::Quaternion modelrot, const Ogre::Quaternion parentsInitialWorldOrientation = Ogre::Quaternion::IDENTITY);
	void					renderDependants();
	vector<int>			dependantActor;		//an actor with no primitives but has model(s) that want to attach to the bone
	ScytheSkeleton*		skeleton;			//pointer to owner
};

class ScytheSkeleton
{
public:
	ScytheSkeleton(){  }

	bool				setup(Ogre::Entity* ent, Scythe::SkeletonData* skelData);

	//we call this each frame
	void				updateRagdoll();	

	//this is technically inverse ragdoll.  It matches the position of the ragdoll primitives to the 
	//position of the character bones.  Can be used at ragdoll creation, to make the ragdoll
	//match the character before collapsing.
	void				setRagdollToSkeleton();
	
	//this function sets a bone to have its orientation controlled by an actor (ragdoll mode)
	//if false then it will act normally.  default = false;  Should be set in the createBodyCallback, because
	//not every bone is guaranteed to be part of the ragdoll (eg fingers and toes)
	void				setBoneIsRag(bool rag, std::string boneName);
	//if a model attaches to a bone but has no physics body, we use this function to attach it
	void				attachDependantModel(std::string boneName, int modelID);

	Ogre::Entity*			entity;
	Scythe::SkeletonData*	scytheData;	//for the reference to Scythe

private:

	vector<ScytheBone*>			bonelist;	//list of all the characters bones
	Ogre::SkeletonInstance*		skel;
	ScytheBone*				getBone(string name);
	ScytheBone*				rootBone;		//this is the one we use to start the render chain
};

//handy conversion functions for ogre
inline Scythe::Matrix toScy(const Ogre::Matrix3 &m) 
{
	return *(Scythe::Matrix*)&m;
}
inline Scythe::Vector3 toScy(const Ogre::Vector3 &m) 
{
	return Scythe::Vector3(m.x, m.y, m.z);
}
